// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "PawnBaseCpp.h"
#include "Camera/CameraComponent.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/SpringArmComponent.h"
#include "PaperSpriteComponent.h"
#include "PaperFlipbookComponent.h"
#include "Components/AudioComponent.h"

#include "PlayerBaseCpp.generated.h"

UENUM(Blueprintable)
enum class EAnimEnum : uint8 { E_IdleRight, E_IdleLeft, E_RunRight, E_RunLeft, E_AttackRight, E_AttackLeft, E_JumpRight, E_JumpLeft,
	E_DeadLeft, E_DeadRight, E_None };

UENUM(Blueprintable)
enum class EActionEnum : uint8 { E_Idle, E_RunRight, E_RunLeft, E_Attack, E_Jump, E_Dead };

class UInventoryComponentBaseCpp;
class UAttackComponentBaseCpp;
class UHPComponentBaseCpp;

/**
 * 
 */
UCLASS()
class ACTIONGAME_API APlayerBaseCpp : public APawnBaseCpp
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UCameraComponent* FollowCamera;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	USpringArmComponent* CameraArm;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UPaperSpriteComponent* SpriteShip;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UPaperFlipbookComponent* AnimIdleLeft;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UPaperFlipbookComponent* AnimIdleRight;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UPaperFlipbookComponent* AnimRunLeft;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UPaperFlipbookComponent* AnimRunRight;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UAudioComponent* Audio;
	
	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float WidthMargin = 200.0;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float TopMargin = 200.0;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float BottomMargin = 200.0;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	EAnimEnum AnimState;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	EActionEnum ActionState;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float JumpForce;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float KillRange;

	UPROPERTY(EditAnywhere, BlueprintReadOnly)
	float BaseDamage;

protected:
	bool IsJumping;
	bool AbilityBusy;

	int MaxJumpCnt;
	int CurrentJumpCnt;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	FTimerHandle AbilityTimerHandle;
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	FTimerHandle KillTimerHandle;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	FTimerHandle AbilityProTimerHandle;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	UInventoryComponentBaseCpp* InventoryComponent;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	UAttackComponentBaseCpp* AttackComponent;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
	UHPComponentBaseCpp* HPComponent;
public:
	APlayerBaseCpp();

	/**
	 * 根据目标动画状态设置动画资源，蓝图中实现。
	 */
	UFUNCTION(BlueprintImplementableEvent)
	void UpdateAnimStateMachine(const EAnimEnum State);

	UFUNCTION()
	void OnHitGround(UPrimitiveComponent* HitComponent, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);

	/**
	 * 左右移动，其动画可被攻击的动画打断，但仍不影响移动。
	 */
	virtual void MoveRight(float Axis);

	/**
	 * 跳跃函数，对box施加向上的脉冲力，可实现多段跳，由MaxJumpCnt控制。
	 */
	virtual void MoveJump();

	/**
	 * 攻击函数，开启两个定时器，一个用于攻击动画，另一个用于施加伤害。
	 */
	virtual void Attack();

	/**
	 * 高级攻击函数
	 */
	virtual void AttackPro();

	virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;

	/**
	 * 根据状态，用于播放音效，蓝图中实现。
	 */
	UFUNCTION(BlueprintImplementableEvent)
    void PlayAudio(EActionEnum CurrentAction);

	/**
	* 返回背包组件
	* @return InventoryComponent 背包组件
	*/
	UInventoryComponentBaseCpp* GetInventoryComponent() const;

	/**
	 * 返回HP组件
	 * @return HPComponent HP组件
	 */
	UHPComponentBaseCpp* GetHPComponent() const;

	/**
	 * 返回攻击组件
	 * @return AttackComponent 攻击组件
	 */
	UAttackComponentBaseCpp* GetAttackComponent() const;
	
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	/**
	 * 攻击动作的回调函数，维护一个攻击锁。
	 */
	void AbilityTimerCallback();

	/**
	 * 高级攻击动作的回调函数
	 */
	void AbilityProTimerCallback();

	/**
	 * 施加伤害计时器 的回调函数。
	 */
	void KillTimerCallback();

	/**
	 * 自动调节相机位置。
	 * @param CurrentCameraArmLocation 当前相机在世界中的位置。
	 * @param CurrentPlayerLocation 当前玩家角色在世界中的位置。
	 * @param Delta 相机位置偏移量。
	 */
	inline void UpdateCameraLocation(const FVector& CurrentCameraArmLocation, const FVector& CurrentPlayerLocation, FVector& Delta);

	/**
	 * 动画状态机
	 */
	inline EAnimEnum GetAnimStateByAction(EActionEnum& CurrentAction, EActionEnum TargetAction);

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
};
